using System;

namespace Rubikev.Common.DependencyInjection
{
   /// <summary>
   /// Interface for registering types for dependency injection
   /// Unfortunately, it can't be mocked, as Castle Proxy doesn't like the "where TImplementation : TContract" constraint
   /// </summary>
   public interface ITypeRegister
   {
      /// <summary>
      /// Registers an implementation type for a contract type
      /// </summary>
      /// <param name="scope">The optional scope for the type. Defaults to singleton</param>
      /// <typeparam name="TContract">The type of the contract that the implementation implements</typeparam>
      /// <typeparam name="TImplementation">The type of the implementation that will be used when the <typeparamref name="TContract"/> is requested</typeparam>
      void RegisterType<TContract, TImplementation>(LifetimeScope scope = LifetimeScope.Singleton) where TImplementation : TContract;

      /// <summary>
      /// Registers a creation method for a contract type
      /// </summary>
      /// <param name="creationMethod">The method used to create an instance that implements the contract</param>
      /// <param name="scope">The optional scope for the type. Defaults to singleton</param>
      /// <typeparam name="TContract">The type of the contract that the <paramref name="creationMethod"/> returns</typeparam>
      void RegisterType<TContract>(Func<TContract> creationMethod, LifetimeScope scope = LifetimeScope.Singleton);

      /// <summary>
      /// Registers an implementation type for a contract type. This is provided for open generic support
      /// </summary>
      /// <param name="scope">The optional scope for the type. Defaults to singleton</param>
      /// <param name="contractType">The type of the contract that the implementation implements</param>
      /// <param name="implementationType">The type of the implementation that will be used when the <paramref name="contractType"/> is requested</param>
      void RegisterType(Type contractType, Type implementationType, LifetimeScope scope = LifetimeScope.Singleton);
   }
}